/*************************************************************************************
*Copyright (c) 2011, Intel Mobile Communications GmbH. 
*All rights reserved.
*
*Redistribution and use in source and binary forms, with or without
*modification, are permitted provided that the following conditions are met:
*    * Redistributions of source code must retain the above copyright
*      notice, this list of conditions and the following disclaimer.
*    * Redistributions in binary form must reproduce the above copyright
*      notice, this list of conditions and the following disclaimer in the
*      documentation and/or other materials provided with the distribution.
*    * Neither the name of the <organization> nor the
*      names of its contributors may be used to endorse or promote products
*      derived from this software without specific prior written permission.
*
*THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
*ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
*WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
*DISCLAIMED. IN NO EVENT SHALL INTEL MOBILE COMMUNICATIONS GMBH. BE LIABLE FOR ANY
*DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
*(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
*LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
*ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
*(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
*SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*************************************************************************************/

/*
This file contains samples of  the code for the article,
"Processing XML with Xerces and the DOM" by Ethan McCallum (2005/09/08)
Published on ONLamp.com (http://www.onlamp.com/)
http://www.onlamp.com/pub/a/onlamp/2005/09/08/xerces_dom.html
*/

#ifndef CEF_PARSER_H
#define CEF_PARSER_H
#include<xercesc/dom/DOM.hpp>
#include<xercesc/dom/DOMDocument.hpp>
#include<xercesc/dom/DOMDocumentType.hpp>
#include<xercesc/dom/DOMElement.hpp>
#include<xercesc/dom/DOMImplementation.hpp>
#include<xercesc/dom/DOMImplementationLS.hpp>
#include<xercesc/dom/DOMNodeIterator.hpp>
#include<xercesc/dom/DOMNodeList.hpp>
#include<xercesc/dom/DOMText.hpp>
#include<xercesc/util/XMLUni.hpp>
#include<xercesc/util/XMLString.hpp>
#include<xercesc/dom/DOMLSSerializerFilter.hpp>
#include<xercesc/dom/DOMLSSerializer.hpp>
#include<xercesc/framework/LocalFileFormatTarget.hpp>
#include<xercesc/parsers/XercesDOMParser.hpp>
#include <xercesc/framework/MemBufInputSource.hpp>
#include "cef.h" 
#include "cef_domain.h"
#include "cef_block.h"
#include "cef_dvfs_point.h"
#include "cef_flow.h"
#include "cef_initiator.h"
#include "cef_link.h"
#include "cef_routes.h"
#include "cef_system.h"
#include "cef_system_properties.h"
#include "cef_target.h"
#include "cef_usecase.h"
#include <string>
#include <vector>
#include <list>
#include <algorithm>
#include <stdio.h>
#include <sstream>
#include<functional>
#include<iterator>
#include<stdexcept>

struct FreeXercesString {

	static void releaseXMLString( XMLCh* str ) {
		xercesc::XMLString::release( &str ) ;
		return ;
	}

	static void releaseCString( char* str ) {
		xercesc::XMLString::release( &str ) ;
		return ;
	}

} ;

class StringManager {

	private:
	typedef std::list< XMLCh* > XMLStringList ;
	typedef std::list< char* > CStringList ;

	XMLStringList xmlStrings_ ;
	CStringList cStrings_ ;

	protected:
	// empty

	public:
	StringManager() ;

	/// destroys the strings in the various lists
	~StringManager() throw() ;


	/// frees memory of all owned strings
	void drain() throw() ;


	/**
	\brief grant ownership of the string to the calling code

	throw std::logic_error if the specified string isn't found
	*/
	char* disown( char* str ) throw( std::logic_error ) ;


	/**
	\brief grant ownership of the string to the calling code

	throw std::logic_error if the specified string isn't found
	*/
	XMLCh* disown( XMLCh* str ) throw( std::logic_error ) ;


	/**
	\brief transcode the supplied C string to XMLCh* and take ownership of the XMLCh*

	The returned XMLCh* will be added to the const pool; calls to own() must therefore
	pass a const XMLCh* parameter
	*/

	XMLCh* convert( const char* str ) ;


	/**
	\brief transcode the supplied C++ string to XMLCh* and take ownership of the XMLCh*

	The returned XMLCh* will be added to the const pool; calls to own() must therefore
	pass a const XMLCh* parameter
	*/

	XMLCh* convert( const std::string& str ) ;


	/**
	\brief transcode the supplied XMLCh* to a C string and take ownership of the C string

	The returned char* will be added to the const pool; calls to own() must therefore
	pass a const char* parameter
	*/
	char* convert( const XMLCh* str ) ;

} ;
class cef_tags
{
	public:
	XMLCh* communication;
	XMLCh* cef;
	XMLCh* usecase;
	XMLCh* system;
	XMLCh* domains;
	XMLCh* domain;
	XMLCh* system_properties;
	XMLCh* blocks;
	XMLCh* block;
	XMLCh* links;
	XMLCh* link;
	XMLCh* routes;
	XMLCh* route;
	XMLCh* fp_bounding_box;
	XMLCh* x;
	XMLCh* y;
	XMLCh* clocks;
	XMLCh* clock;
	XMLCh* name;
	XMLCh* id;
	XMLCh* frequency;
	XMLCh* skew;
	XMLCh* derived_from_id;
	XMLCh* derivation_type;
	XMLCh* derivation_phase;
	XMLCh* power_networks;
	XMLCh* power_network;
	XMLCh* power_network_id;
	XMLCh* voltage;
	XMLCh* clock_id;
	XMLCh* operating_points;
	XMLCh* operating_point;
	XMLCh* shutdownallowed;
	XMLCh* type;
	XMLCh* connections;
	XMLCh* share_edge_with;
	XMLCh* ports;
	XMLCh* port;
	XMLCh* protocol;
	XMLCh* protocol_variant;
	XMLCh* max_outstanding_transactions;
	XMLCh* address_width;
	XMLCh* read_data_width;
	XMLCh* write_data_width;
	XMLCh* orientation;
	XMLCh* size;
	XMLCh* soft;
	XMLCh* shape;
	XMLCh* corners;
	XMLCh* corner;
	XMLCh* area;
	XMLCh* aspectratio;
	XMLCh* bottom_left_corner_position;
	XMLCh* movable;
	XMLCh* initial_x;
	XMLCh* initial_y;
	XMLCh* rotatable;
	XMLCh* mirrorable;
	XMLCh* rotation;
	XMLCh* initial_rotation;
	XMLCh* mirroring_x;
	XMLCh* initial_mirroring_x;
	XMLCh* mirroring_y;
	XMLCh* initial_mirroring_y;
	XMLCh* layer;
	XMLCh* domain_id;
	XMLCh* architecture;
	XMLCh* clock_divider;
	XMLCh* buffers;
	XMLCh* in;
	XMLCh* out;
	XMLCh* address_ranges;
	XMLCh* address_range;
	XMLCh* start;
	XMLCh* inports;
	XMLCh* outports;
	XMLCh* input_buffers;
	XMLCh* depth;
	XMLCh* output_buffers;
	XMLCh* flit_width;
	XMLCh* virtual_channels;
	XMLCh* virtual_channel_arbitration_structure;
	XMLCh* source;
	XMLCh* destination;
	XMLCh* number;
	XMLCh* width;
	XMLCh* carries_source_clock;
	XMLCh* carries_source_reset;
	XMLCh* link_length_estimation;
	XMLCh* out_port_number;
	XMLCh* in_port_number;
	XMLCh* blocks_on_link;
	XMLCh* block_on_link;
	XMLCh* routingpolicy;
	XMLCh* source_routing;
	XMLCh* switches;
	XMLCh* switch_;
	XMLCh* outport;
	XMLCh* linknum;
	XMLCh* route_weight;
	XMLCh* distributed_routing;
	XMLCh* tables;
	XMLCh* table;
	XMLCh* switch_id;
	XMLCh* destination_id;
	XMLCh* input_port;
	XMLCh* output_ports;
	XMLCh* output_port;
	XMLCh* lbdr;
	XMLCh* lbdr_entry;
	XMLCh* lbdr_routing_bits;
	XMLCh* lbdr_connectivity_bits;
	XMLCh* lbdr_deroute_bits;
	XMLCh* lbdr_fork_bits;
	XMLCh* fdor;
	XMLCh* fdor_entry;
	XMLCh* fdor_bit;
	XMLCh* virtual_networks;
	XMLCh* virtual_network;
	XMLCh* vc_id;
	XMLCh* use_case;
	XMLCh* dvfs;
	XMLCh* dvfs_point;
	XMLCh* initiators;
	XMLCh* initiator;
	XMLCh* initiator_port_id;
	XMLCh* targets;
	XMLCh* target;
	XMLCh* target_port_id;
	XMLCh* flows;
	XMLCh* flow;
	XMLCh* flow_type;
	XMLCh* peak_bandwidth;
	XMLCh* sustained_bandwidth;
	XMLCh* burst_transfers;
	XMLCh* burst_transfer;
	XMLCh* transfer_size;
	XMLCh* period;
	XMLCh* transfer_offset;
	XMLCh* transfer_duration;
	XMLCh* lat_zl;
	XMLCh* lat_rt;
	XMLCh* gid;
	XMLCh* burstiness;
	XMLCh* burst;
	XMLCh* length;
	XMLCh* percent;
	XMLCh* vendor;
	XMLCh* vendor_id;
	XMLCh* vendor_name;
	XMLCh* fp_width;
	XMLCh* fp_height;
	XMLCh* cef_version;
	XMLCh* block_type;
	XMLCh* connection_with_id;
	XMLCh* position_x;
	XMLCh* position_y;
	XMLCh* ni_type;
	XMLCh* arbitration_policy;
	XMLCh* source_port_id;
	XMLCh* destination_port_id;
	XMLCh* auxilary_backward_wires;
	XMLCh* auxilary_forward_wires;
	XMLCh* source_id;
	XMLCh* switch_output_port_ids;
	XMLCh* switch_output_port_id;
	XMLCh* output_port_id;
	XMLCh* lbdr_deroutes;
	XMLCh* lbdr_deroute;
	XMLCh* input_port_id;
	XMLCh* deroute_port;
	XMLCh* lbdr_forks;
	XMLCh* lbdr_fork;
	XMLCh* fork_ports;
	XMLCh* fork_port;
	XMLCh* fdor_bits;
	XMLCh* vc_ids;
	XMLCh* domain_operating_points;
	XMLCh* operating_point_id;
	XMLCh* weight;
	XMLCh* zero_load_latency_bound;
	XMLCh* latency_bound;
	XMLCh* priority_class;
	XMLCh* virtual_channel_arbitration_policy;
	
	cef_tags();
	~cef_tags();
	
};


class cef_parser
{
	private:	
	cef* mycef;	
	cef_system* system;
	cef_system_properties* system_properties;
	std::vector<cef_domain*>* domains;
	std::vector<cef_block*>* blocks;
	std::vector<cef_link*>* links;
	cef_routes* routes;
	std::vector<cef_usecase*>* communication;
	StringManager* sm;
	cef_tags tags;

	xercesc::DOMDocument* wDoc;	
	xercesc::XercesDOMParser myparser;

	std::string getText(xercesc::DOMElement*);
	bool toBool(std::string);
	unsigned long long str2u(std::string);
	std::string u2str(unsigned long long);
	//Main routines
	void handleBlocks(xercesc::DOMElement*);
	void handleDomains(xercesc::DOMElement*);
	void handleUsecases(xercesc::DOMElement*);
	void handleLinks(xercesc::DOMElement*);
	
	
	
	//Subroutines
 
	cef* handleCEF(xercesc::DOMElement*);
	cef_block* handleBlock(xercesc::DOMElement*);	
	cef_domain* handleDomain(xercesc::DOMElement*);
	cef_system* handleSystem(xercesc::DOMElement*);
	cef_link* handleLink(xercesc::DOMElement*);
	cef_burst_trans* handleBurstTrans(xercesc::DOMElement*);
	cef_burst* handleBurst(xercesc::DOMElement*);
	cef_flow* handleFlow(xercesc::DOMElement*);
	cef_usecase* handleUsecase(xercesc::DOMElement*);
	cef_system_properties* handleSystemProperties(xercesc::DOMElement*);
	cef_operating_point* handleOperatingPoint(xercesc::DOMElement*);
	cef_port* handlePort(xercesc::DOMElement*);	
	cef_routes* handleRoutes(xercesc::DOMElement*);
	cef_target* handleTarget(xercesc::DOMElement*);
	cef_initiator* handleInitiator(xercesc::DOMElement*);
	cef_clock* handleClock(xercesc::DOMElement*);
	cef_powernet* handlePowerNet(xercesc::DOMElement*);
	cef_connection* handleConnection(xercesc::DOMElement*);
	cef_block_size* handleBlockSize(xercesc::DOMElement*);
	cef_block_architecture* handleBlockArchitecture(xercesc::DOMElement*);
	cef_block_blc_pos* handleBotLefCor(xercesc::DOMElement*);
	cef_block_orientation* handleBlockOrientation(xercesc::DOMElement*);
	cef_sourcerouting* handleSourceRouting(xercesc::DOMElement*);
	cef_distributedrouting* handleDistributedRouting(xercesc::DOMElement*);
	cef_lbdr* handleLBDR(xercesc::DOMElement*);
	cef_lbdr_entry* handleLBDREntry(xercesc::DOMElement*);
	cef_lbdr_fork* handleLBDRFork(xercesc::DOMElement*);
	cef_fdor* handleFDOR(xercesc::DOMElement*);
	cef_virtual_network* handleVirtualNet(xercesc::DOMElement*);
	
	//Reverse routines
	xercesc::DOMElement* convertCommunication(std::vector<cef_usecase*>*);
	xercesc::DOMElement* convertSystem(std::vector<cef_system*>*);
	xercesc::DOMElement* convertSystemProperties(cef_system_properties*);
	xercesc::DOMElement* convertUsecase(cef_usecase*);
	xercesc::DOMElement* convertInitiator(cef_initiator*);
	xercesc::DOMElement* convertTarget(cef_target*);
	xercesc::DOMElement* convertFlow(cef_flow*);
	xercesc::DOMElement* convertBurst(cef_burst*);
	xercesc::DOMElement* convertBurstTrans(cef_burst_trans*);
	xercesc::DOMElement* convertSystem(cef_system*);
	//xercesc::DOMElement* convertSystemProperties(cef_system_properties*);
	xercesc::DOMElement* convertDomain(cef_domain*);
	xercesc::DOMElement* convertPowerNet(cef_powernet*);
	xercesc::DOMElement* convertClock(cef_clock*);
	xercesc::DOMElement* convertOperatingPoint(cef_operating_point*);
	xercesc::DOMElement* convertLink(cef_link*);
	xercesc::DOMElement* convertBlock(cef_block*);
	xercesc::DOMElement* convertPort(cef_port*);
	xercesc::DOMElement* convertBlockSize(cef_block_size*);
	xercesc::DOMElement* convertBlockPosition(cef_block_blc_pos*);
	xercesc::DOMElement* convertBlockOrientation(cef_block_orientation*);
	xercesc::DOMElement* convertBlockArchitecture(cef_block_architecture*);
	xercesc::DOMElement* convertRoutes(cef_routes*);
	xercesc::DOMElement* convertSourceRouting(cef_sourcerouting*);
	xercesc::DOMElement* convertSrcRoute(cef_src_route*);
	xercesc::DOMElement* convertDistributedRouting(cef_distributedrouting*);
	xercesc::DOMElement* convertTable(cef_routing_table*);
	xercesc::DOMElement* convertLBDR(cef_lbdr*);
	xercesc::DOMElement* convertLBDREntry(cef_lbdr_entry*);
	xercesc::DOMElement* convertLBDRFork(cef_lbdr_fork*);
	xercesc::DOMElement* convertFDOR(cef_fdor*);
	xercesc::DOMElement* convertVirtualNets(std::vector<cef_virtual_network*>*);
	xercesc::DOMElement* convertVirtualNet(cef_virtual_network*);

	
	
//	xercesc::DOMElement* getLinks(std::vector<cef_link*>*);
//	xercesc::DOMElement* getSystem(cef_system*);
//	xercesc::DOMElement* getSystemProperties(cef_system_properties*);
//	xercesc::DOMElement* getDomains(std::vector<cef_domain*>*);
//	xercesc::DOMElement* getRoutes(std::vector<cef_routes*>*);
//	
//	//Reverse subroutines	
//	xercesc::DOMElement* getPort(cef_port*);	
//	xercesc::DOMElement* getBlock(cef_block*);
//	xercesc::DOMElement* getDomain(cef_domain*);
//	xercesc::DOMElement* getLink(cef_link*);
//	xercesc::DOMElement* getFlow(cef_flow*);
//	xercesc::DOMElement* getRoutes(cef_routes*);
//	xercesc::DOMElement* getTarget(cef_target*);
//	xercesc::DOMElement* getInitiator(cef_initiator*);
//	xercesc::DOMElement* getClock(cef_clock*);
//	xercesc::DOMElement* getPowerNet(cef_powernet*);
//	xercesc::DOMElement* getConnection(cef_connection*);
//	xercesc::DOMElement* getBlockSize(cef_block_size*);
//	xercesc::DOMElement* getBlockArchitecture(cef_block_architecture*);
//	xercesc::DOMElement* getBotLefCor(cef_block_blc_pos*);
//	xercesc::DOMElement* getBlockOrientation(cef_block_orientation*);
//	xercesc::DOMElement* getSourceRouting(cef_sourcerouting*);
//	xercesc::DOMElement* getDistributedRouting(cef_distributedrouting*);
//	xercesc::DOMElement* getRoutingTable(cef_routing_table*);
//	xercesc::DOMElement* getLBDR(cef_lbdr*);
//	xercesc::DOMElement* getLBDREntry(cef_lbdr_entry*);
//	xercesc::DOMElement* getFDOR(cef_fdor*);
//	xercesc::DOMElement* getUsecase(cef_usecase*);
	xercesc::DOMDocument* newCEF();	
	public:
	cef_parser();
	~cef_parser();
	cef* parseXML(std::string);
	void writeXML(cef*, std::string);
};

#endif
